﻿using System.Windows;
using System.Windows.Controls;
using Red.Controls.Shell;
using Red.Controls.ViewModels;
using Red.Core;
using Red.EngineData.View;

namespace Red.Controls
{
    /// <summary>
    /// Interaction logic for RedContextMenu.xaml
    /// </summary>
    public partial class RedContextMenu : ContextMenu
    {
        #region Data

        private DataView _interopContext = null;

        #endregion

        #region Constructor

        public RedContextMenu()
        {
            InitializeComponent();

            DataContextChanged += RedContextMenu_DataContextChanged;
        }

        #endregion

        #region Callbacks

        /// <summary>
        /// Checks all items and sets interop context to all interop commands
        /// </summary>
        protected override void OnItemsSourceChanged( System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue )
        {
            if ( newValue != null )
            {
                foreach ( var item in newValue )
                {
                    SetInteropContext( item as RedMenuDataItem );
                }
            }

            base.OnItemsSourceChanged( oldValue, newValue );
        }

        private void SetInteropContext( RedMenuDataItem item )
        {
            if ( item == null )
                return;

            var wrapper = item.Wrapper;

            if ( wrapper?.Command is RedInteropCommand )
            {
                var interopCmd = wrapper?.Command as RedInteropCommand;
                interopCmd.InteropContext = _interopContext;
            }

            foreach ( var child in item.Children )
            {
                SetInteropContext( child );
            }
        }

        /// <summary>
        /// Checks data context and tries to extract interop context
        /// </summary>
        private void RedContextMenu_DataContextChanged( object sender, DependencyPropertyChangedEventArgs e )
        {
            if ( e.NewValue is TreeItemEngine )
            {
                var treeItem = e.NewValue as TreeItemEngine;
                _interopContext = treeItem.View;
            }
            else if ( e.NewValue is InteropDataItem )
            {
                var dataItem = e.NewValue as InteropDataItem;
                _interopContext = dataItem.Data;
            }
        }

        #endregion

        #region RedMenuItem Callbacks

        /// <summary>
        /// Calls interop functor for correct interop command
        /// </summary>
        private void RedMenuItem_OnClick( object sender, RoutedEventArgs e )
        {
            var data = (sender as MenuItem)?.DataContext as RedMenuDataItem;

            var interopCommand = data?.Wrapper?.Command as RedInteropCommand;

            var interopContext = interopCommand?.InteropContext as DataView;

            if ( interopContext == null )
                return;

            var functorContext = interopContext.GetSubView( interopCommand.InteropFunctorName );
            functorContext.Refresh(
                ex => 
                {
                    if ( ex != null )
                    {
                        data.IsEnabled = false;
                        RedMessageBox.ShowAsync( this, RedDialogType.Ok, ex.Message, "Action error" );
                        return;
                    }

                    var interopFunctionName = "";

                    if ( functorContext.Children.Count > 0 )
                    {
                        var dialog = new RunEngineActionDialog( interopContext, functorContext, interopCommand.InteropFunctorParamNames ) { Owner = Window.GetWindow( this ) };
                        dialog.Show();
                    }
                    else
                    {
                        interopContext.Execute( Interop.Make( interopFunctionName + "()" ),
                            result =>
                            {
                                if ( string.IsNullOrEmpty( result.Data ) == false && result.Data != "{void}" )
                                {
                                    RedMessageBox.ShowAsync( this, RedDialogType.Ok, result.Data, "Action result" );
                                }
                            },
                            exInternal =>
                            {
                                RedMessageBox.ShowAsync( this, RedDialogType.Ok, exInternal.Message, "Action error" );
                            } );
                    }
                } );
        }

        #endregion
    }
}
